package jast;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

import lexer.JavaLexer;
import parser.JavaParser;
import path.BranchNode;
import path.PathRec;
import path.SwitchBranchNode;
/**
 * 输出基本路径集合
 * 只支持类中单个方法
 * TODO 支持对类中所有方法进行分析
 */
public class PrimePathGen {
	private BranchNode exitNode = null;
	private ArrayList<PathRec> pathList = new ArrayList<PathRec>();

	public void genPrimePath(String fileName) {
		try {
			ANTLRInputStream input = new ANTLRInputStream(new FileInputStream(fileName));
			JavaLexer lexer = new JavaLexer(input);
			CommonTokenStream tokens = new CommonTokenStream(lexer);
			JavaParser parser = new JavaParser(tokens);
			ParseTree tree = parser.compilationUnit();

			ParseTreeWalker walker = new ParseTreeWalker();
			CfgListener listener = new CfgListener(parser);
			walker.walk(listener, tree);
			exitNode = listener.methodExit;
			visitPrimePath(listener.methodStart.get(0), new PathRec());
			for (int i = 0; i < pathList.size(); i++) {
				System.out.println("Path" + i + ":");
				pathList.get(i).showPath();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 基本路径集合
	 * 
	 * @param next
	 * @param pr
	 */
	public void visitPrimePath(BranchNode next, PathRec pr) {
		if (next.equals(exitNode)) {
			pathList.add(pr);
			return;
		}
		// 判断是否遍历过
		if (next.visited) {
			// 加入路径
			if (next.branchNum != -1) {
				pr.path.add(next);
			}
			if (next.type == 2)
				visitPrimePath(next.exitNode, pr);
			else if (next.type == 3)
				visitPrimePath(((SwitchBranchNode) next).caseList.get(0), pr.copy());
			else {// (next.getLeft() != null && next.getRight() !=
					// null),next.getRight() == null
				if (next.getLeft() != null)
					visitPrimePath(next.getLeft(), pr.copy());// 已遍历过，只走一个分支继续
				else
					visitPrimePath(next.getRight(), pr.copy());
			}
		} else {
			// 加入路径
			if (next.branchNum != -1) {
				pr.path.add(next);
			}
			next.visited = true;
			if (next.type == 3)
				for (int i = 0; i < ((SwitchBranchNode) next).caseList.size(); i++) {
					visitPrimePath(((SwitchBranchNode) next).caseList.get(i), pr.copy());
				}
			else {
				if (next.getLeft() != null) {
					visitPrimePath(next.getLeft(), pr.copy());
				}
				if (next.getRight() != null) {
					visitPrimePath(next.getRight(), pr.copy());
				}
			}
		}
	}

	public static void main(String[] args) throws Exception {
		(new PrimePathGen()).genPrimePath("src/test/TestTarget.java");
	}

}